<#ftl strip_whitespace=true >
package ${daoPackageName!};

import ${entityPackageName}.${name};
import ${entityPackageName}.${jpaName};
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import org.springframework.stereotype.Repository;

<#list importedTypes as type>
import ${type};
</#list>

@Repository
public class ${jpaDaoName} implements ${daoName} {

	@PersistenceContext private EntityManager em;

	public ${name} create${name}(<#list mandatoryAttributeList as attr>${attr.type} ${attr.name}<#if attr_has_next>, </#if></#list>) {
		return new ${jpaName}(<#list mandatoryAttributeList as attr>${attr.name}<#if attr_has_next>, </#if></#list>);
	}
	
	public ${name} findById(Long id) {
		return em.find(${jpaName}.class, id);
	}
	
	@SuppressWarnings("unchecked")
	public List<${name}> findAll() {
		Query q = em.createQuery("from ${name} t");
		return q.getResultList();
	}
	
	public void store(${name} v) {
		em.persist(v);
	}
	
	public void store(List<${name}> l) {
		for (${name} entity: l) {
			store(entity);
		}
	}
	
	public void delete(${name} v) {
		em.remove(v);
	}
	
	<#list attributes as attribute>
		<#if !(attribute.calculatedValue??) && !(attribute.identifier)>
			<#if attribute.unique>
	public ${name} findBy${attribute.nameCapitalized}(${attribute.shortTypeName} val) {
		Query q = em.createQuery("from ${name} t where t.${attribute.name} = :param");
		q.setParameter("param", val);
		try {
			return (${name}) q.getSingleResult();
		} catch (NoResultException e) {
			return null;
		}
	}
	
			<#else>
	@SuppressWarnings("unchecked")
	public List<${name}> findBy${attribute.nameCapitalized}(${attribute.shortTypeName} val) {
		Query q = em.createQuery("from ${name} t where t.${attribute.name} = :param");
		q.setParameter("param", val);
		return q.getResultList();
	}
	
			</#if>
		</#if>
	</#list>
	<#list uniqueConstraints as uc>
	public ${name} findBy<#list uc.attributes as attr>${attr.nameCapitalized}</#list>(<#list uc.attributes as attr>${attr.type} ${attr.name}<#if attr_has_next>, </#if></#list>) {
		Query q = em.createQuery("from ${name} t where <#list uc.attributes as attr>t.${attr.name} = :${attr.name}<#if attr_has_next> and </#if></#list>");
		<#list uc.attributes as attr>
		q.setParameter("${attr.name}", ${attr.name});
		</#list>
		try {
			return (${name}) q.getSingleResult();
		} catch (NoResultException e) {
			return null;
		}
	}

	</#list>
	<#list finders as finder>
	public <#if finder.typeMany>List<${name}><#else>${name}</#if> ${finder.name}(<#list finder.finderOperations as fo>${fo.attribute.type} ${fo.paramName}<#if fo_has_next>, </#if></#list><#if finder.typeMany && finder.limited><#if !finder.emptyFinderOperationList>, </#if>int maxRowCount</#if>) {
		String queryString = "from ${name} t where <#list finder.finderOperations as fo>t.${fo.attribute.name} = :${fo.paramName}<#if fo_has_next> and </#if></#list>";
		<#if finder.ordered>
		queryString += " order by";
			<#list finder.orderBys as o>
		queryString += " t.${o.attribute.name}<#if o.descending> desc</#if><#if o_has_next>, </#if>";	
			</#list>
		</#if>
		Query q = em.createQuery(queryString);
		<#list finder.finderOperations as fo>
		q.setParameter("${fo.attribute.name}", ${fo.paramName});
		</#list>
		<#if finder.typeMany>
			<#if finder.limited>
		q.setMaxResults(maxRowCount);	
			</#if>
		return q.getResultList();
		<#else>
		try {
			return (${name}) q.getSingleResult();
		} catch (NoResultException e) {
			return null;
		}
		</#if>
	}
	
	</#list>

}